#include "CMainWindow.h"
#include "ui_CMainWindow.h"
#include <algorithm>
#include <iostream>
#include <QApplication>
#include <QDebug>
#include <QPixmap>
#include <QFileDialog>
#include <QMessageBox>

using namespace std;

const QString CMainWindow::K_REZISE_PIXEL_W_AR = "Pixel Resize w aspect ratio";
const QString CMainWindow::K_REZISE_PIXEL_WO_AR = "Pixel Resize w/o aspect ratio";

const QString CMainWindow::K_GRAY_SCALE_AVERAGE = "Average";
const QString CMainWindow::K_GRAY_SCALE_LIGHTNESS = "Lightness";
const QString CMainWindow::K_GRAY_SCALE_LUMINOSITY = "Luminosity";

CMainWindow::CMainWindow(QWidget *parent) :QMainWindow(parent), m_ui(new Ui::CMainWindow)
{
    m_ui->setupUi(this);

    m_ui->m_cbResizeAlgOption->addItem(K_REZISE_PIXEL_W_AR);
    m_ui->m_cbResizeAlgOption->addItem(K_REZISE_PIXEL_WO_AR);

    m_ui->m_cbGrayScaleAlgOption->addItem(K_GRAY_SCALE_AVERAGE);
    m_ui->m_cbGrayScaleAlgOption->addItem(K_GRAY_SCALE_LIGHTNESS);
    m_ui->m_cbGrayScaleAlgOption->addItem(K_GRAY_SCALE_LUMINOSITY);

    m_ui->m_mainFrame->clear();

    connect(m_ui->m_actLoadImage , SIGNAL(triggered()) , this , SLOT(LoadImage()));
    connect(m_ui->m_actSaveImage , SIGNAL(triggered()) , this , SLOT(SaveImage()));

    connect(m_ui->m_btnCrop , SIGNAL(clicked()) , this , SLOT(Crop()));
    connect(m_ui->m_btnResize , SIGNAL(clicked()) , this , SLOT(Resize()));
    connect(m_ui->m_btnGrayScale , SIGNAL(clicked()) , this , SLOT(GrayScale()));
    connect(m_ui->m_btnInvert , SIGNAL(clicked()) , this , SLOT(InvertImage()));

    connect(m_ui->m_mainFrame , SIGNAL(tabCloseRequested(int)) , SLOT(CloseTab(int)));
}

void CMainWindow::CloseTab(int index)
{
    m_ui->m_mainFrame->removeTab(index);
}

const QPixmap* CMainWindow::GetActualImage()
{
     QWidget* widget = m_ui->m_mainFrame->currentWidget();

     if (widget != NULL)
     {
         return ((QLabel*)widget)->pixmap();
     }

     PopUpMessage("There is no loaded image , Go to File/LoadImage.");
     return NULL;
}

void CMainWindow::SetActualImage(QImage img)
{
    QPixmap pm;

    pm.convertFromImage(img);

    QWidget* widget = m_ui->m_mainFrame->currentWidget();

    if (widget != NULL)
    {
        ((QLabel*)widget)->setPixmap(pm);
    }
}

void CMainWindow::LoadImage()
{
    QString fileName = QFileDialog::getOpenFileName(this,
                       tr("Open Image"), "/home/", tr("Image Files (*.png *.jpg *.bmp)"));

    if(fileName.isNull())
    {
        PopUpMessage("Choose an image file.");
        return;
    }

    QPixmap *imagem = new QPixmap(fileName);

    QLabel* label = new QLabel(m_ui->m_mainFrame);

    label->setPixmap(*imagem);

    m_ui->m_mainFrame->addTab(label, "untitled");
}

void CMainWindow::SaveImage()
{
    QString fileName = QFileDialog::getSaveFileName(this,
                       tr("Save Image"), "/home/", tr("Image Files (*.png *.jpg *.bmp)"));

    if( fileName.isNull() )
    {
        //qDebug() << fileName.toAscii();
        return ;
    }

    QWidget* widget = m_ui->m_mainFrame->currentWidget();

    if (widget == NULL)
    {
        PopUpMessage("No image to save.");
        return;
    }

    ((QLabel*)widget)->pixmap()->toImage().save(fileName);

    m_ui->m_mainFrame->removeTab(m_ui->m_mainFrame->currentIndex());

    QPixmap *imagem = new QPixmap(fileName);

    QLabel* label = new QLabel(m_ui->m_mainFrame);

    label->setPixmap(*imagem);

    m_ui->m_mainFrame->addTab(label, fileName);
}

void CMainWindow::InvertImage()
{
    const QPixmap* pixMap = GetActualImage();

    QImage img = pixMap->toImage();

    QImage* newImage = new QImage(img.width() , img.height() , QImage::Format_RGB32);

    for (int i = 0; i < img.width(); ++i)
    {
        for(int j = 0; j < img.height(); ++j)
        {
            QColor *color = new QColor(img.pixel(i , j));

            QColor * newColor = new QColor(255 - color->red(),255 - color->green(), 255 - color->blue());

            newImage->setPixel(i , j , newColor->rgb());
        }
    }

    SetActualImage(*newImage);
}

void CMainWindow::GrayScale()
{
    const QPixmap* pixMap = GetActualImage();

    QImage img = pixMap->toImage();

    QImage* newImage = new QImage(img.width() , img.height() , QImage::Format_RGB32);

    QString alg = m_ui->m_cbGrayScaleAlgOption->itemText(m_ui->m_cbGrayScaleAlgOption->currentIndex());

    if (alg == "")
    {
        PopUpMessage("Choose an algorithm form the list.");
        return;
    }

    for (int i = 0; i < img.width(); ++i)
    {
        for (int j = 0; j < img.height(); ++j)
        {
            QColor *color = new QColor(img.pixel(i , j));

            int gray;

            if (alg == CMainWindow::K_GRAY_SCALE_AVERAGE)
            {
                gray = (color->red() + color->green() + color->blue()) / 3;
            }
            else if (alg == CMainWindow::K_GRAY_SCALE_LIGHTNESS)
            {
                gray = (max(color->red() , max(color->green() , color->blue())) + min(color->red() , min(color->green() , color->blue())) ) / 2;
            }
            else
            {
                gray = 0.21 * color->red() + 0.71 * color->green() + 0.07 * color->blue();
            }

            QColor * newColor = new QColor(gray , gray , gray);

            newImage->setPixel(i , j , newColor->rgb());
        }
    }

    SetActualImage(*newImage);
}

//Caso o cara escolha limites maiores do que sua imagem permite sobra para fora.
void CMainWindow::Crop()
{
    const QPixmap* pixMap = GetActualImage();

    if (m_ui->m_txtCropX->toPlainText() == "" ||
        m_ui->m_txtCropY->toPlainText() == "" ||
        m_ui->m_txtCropWidth->toPlainText() == "" ||
        m_ui->m_txtCropHeight->toPlainText() == "")
    {
        PopUpMessage("Fill all the crop Fields.");
        return;
    }

    int x = m_ui->m_txtCropX->toPlainText().toInt();
    int y = m_ui->m_txtCropY->toPlainText().toInt();
    int w = m_ui->m_txtCropWidth->toPlainText().toInt();
    int h = m_ui->m_txtCropHeight->toPlainText().toInt();

    QImage img = pixMap->toImage();

    QImage* newImage = new QImage(w , h , QImage::Format_RGB32);

    for (int i = x , newI = 0; i < w + x; ++i , ++newI)
    {
        if (i >= img.width()) break;

        for (int j = y , newJ = 0; j < h + y; ++j , ++newJ)
        {
            if (j >= img.height()) break;

            newImage->setPixel(newI , newJ , img.pixel(i , j));
        }
    }

    SetActualImage(*newImage);
}

void CMainWindow::Resize()
{
    QString str = m_ui->m_cbResizeAlgOption->itemText(m_ui->m_cbResizeAlgOption->currentIndex());

    if (str == CMainWindow::K_REZISE_PIXEL_W_AR)
    {
        ResizePixelWithAspectRatio();
    }
    else if (str == CMainWindow::K_REZISE_PIXEL_WO_AR)
    {
        ResizePixelWithoutAspectRatio();
    }
}

void CMainWindow::ResizePixelWithAspectRatio()
{
    const QPixmap* pixMap = GetActualImage();

    if (m_ui->m_txtResizeRatio->toPlainText() == "")
    {
        PopUpMessage("Fill the Resize Ratio Field.");
        return;
    }

    float ratio = m_ui->m_txtResizeRatio->toPlainText().toFloat();

    QImage img = pixMap->toImage();

    QImage* newImage = new QImage(img.width() * ratio, img.height() * ratio , QImage::Format_RGB32);

    for (int i = 0; i < newImage->width(); ++i)
    {
        for (int j = 0; j < newImage->height(); ++j)
        {
            newImage->setPixel(i , j , img.pixel((int)(i/ratio) , (int)(j/ratio)));
        }
    }

    SetActualImage(*newImage);
}

void CMainWindow::ResizePixelWithoutAspectRatio()
{
    const QPixmap* pixMap = GetActualImage();

    if (m_ui->m_txtResizeWidth->toPlainText() == "" || m_ui->m_txtResizeHeight->toPlainText() == "")
    {
        PopUpMessage("Fill the Resize Width and the Resize Height Fields.");
        return;
    }

    int width = m_ui->m_txtResizeWidth->toPlainText().toInt();
    int height = m_ui->m_txtResizeHeight->toPlainText().toInt();

    QImage img = pixMap->toImage();

    QImage* newImage = new QImage(width, height , QImage::Format_RGB32);

    for (int i = 0; i < newImage->width(); ++i)
    {
        for (int j = 0; j < newImage->height(); ++j)
        {
            newImage->setPixel(i , j , img.pixel((int)(i * img.width()/width) , (int)(j * img.height()/ height)));
        }
    }

    SetActualImage(*newImage);
}

void CMainWindow::PopUpMessage(const QString msg)
{
    QMessageBox* msgBox = new QMessageBox(m_ui->centralWidget);
    msgBox->setText(msg);
    msgBox->show();
}

CMainWindow::~CMainWindow()
{
    delete m_ui;
}
